home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-03-15 | 73.8 KB | 1,922 lines |
- ! ----------------------------------------------------------------------------
- ! Balances 961216 One of the standard Inform 6 example games
- !
- ! created: 25.9.94
- ! updated: 6.10.94
- ! modernised: 11.12.95
- ! translated to Inform 6: 8.5.96
- ! minor bugs fixed: 16.12.96
- !
- ! This short story was written to demonstrate large-scale programming of
- ! the parser, and features multiple objects, complicated plurals, variable
- ! verbs, objects named by the player and questions. The spell-casting
- ! system is written in a "safe" way so that it could easily be transplanted.
- !
- ! Needs Inform 6, library 6/1 or later to compile.
- ! ----------------------------------------------------------------------------
-
- Release 5;
- Serial "961216";
- Switches d;
-
- Constant Story "BALANCES";
- Constant Headline "^An Interactive Short Story
- ^Copyright (c) 1994, 1995, 1996 by Graham Nelson.^";
-
- Constant OBJECT_SCORE 5;
- Constant MAX_SCORE 51;
-
- Include "Parser";
- Include "VerbLib";
-
- ! ----------------------------------------------------------------------------
- ! The white featureless cubes from "Spellbreaker", which can be identified
- ! by being written on with the magic burin, so that their names are given
- ! by the player in the course of play
- !
- ! A particularly witty thing to do is to give several of them the same name,
- ! or to frotz some of them to distinguish them from the others...
- ! And the game will have no problem with this.
- ! ----------------------------------------------------------------------------
-
- Array cube_text_buffer -> 8;
- Global the_named_word = 0;
- Global from_char; Global to_char;
-
- Class FeaturelessCube
- with number 0 0 0 0, ! There's room for 8 bytes of text in these 4 entries
- description "A perfect white cube, four inches on a side.",
- parse_name
- [ i j flag;
- if (parser_action==##TheSame)
- { for (i=0:i<8:i++)
- if ((parser_one.&number)->i
- ~= (parser_two.&number)->i) return -2;
- return -1;
- }
- for (::i++)
- { j=NextWord(); flag=0;
- if (j=='cube' or 'white' ||
- (j=='featureless' or 'blank' &&
- ((self.&number)->0) == 0)) flag=1;
- if (j=='cubes')
- { flag=1; parser_action=##PluralFound; }
- if (flag==0 && ((self.&number)->0) ~= 0)
- { wn--;
- if (TextReader(0)==0) return i;
- for (j=0: j<8: j++)
- if ((self.&number)->j ~= cube_text_buffer->j)
- return i;
- flag=1;
- }
- if (flag==0) return i;
- }
- ],
- article "a",
- short_name
- [ i; if (((self.&number)->0) == 0) print "featureless white cube";
- else
- { print "~";
- while (((self.&number)->i) ~= 0)
- print (char) (self.&number)->i++;
- print "~ cube";
- }
- rtrue;
- ],
- plural
- [; self.short_name(); print "s";
- ],
- baptise
- [ i; wn = the_named_word;
- if (TextReader(1)==0) return i;
- for (i=0: i<8: i++)
- (self.&number)->i = cube_text_buffer->i;
- self.article="the";
- print_ret "It is now called ", (the) self, ".";
- ],
- has scored;
-
- ! Copies word "wn" from what the player most recently typed, putting it as
- ! plain text into cube_text_buffer, returning false if no such word is there
-
- [ TextReader flag point i j len;
-
- if (flag==1 && from_char~=to_char)
- { for (i=from_char, j=0:i<=to_char && j<7:i++)
- { cube_text_buffer->j = buffer->i;
- if (buffer->i ~= ' ' or ',' or '.') j++;
- }
- for (:j<8:j++) cube_text_buffer->j = 0;
- from_char=0; to_char=0;
- rtrue;
- }
-
- for (i=0:i<8:i++) cube_text_buffer->i = 0;
- if (wn > parse->1) { wn++; rfalse; }
- i=wn*4+1; j=parse->i; point=j+buffer; len=parse->(i-1);
-
- for (i=0:i<len && i<7:i++) cube_text_buffer->i = point->i;
-
- wn++; rtrue;
- ];
-
- Object burin "magic burin"
- with name "magic" "magical" "burin" "pen",
- description
- "This is a magical burin, used for inscribing objects with words
- or runes of magical import. Such a burin also gives you the
- ability to write spell scrolls.",
- before
- [; WriteOn:
- if (second ofclass FeaturelessCube)
- { if (second notin player)
- "Writing on a cube is such a fiddly process that you
- need to be holding it in your hand first.";
- if (burin notin player)
- "You would need some powerful implement for that.";
- second.baptise();
- rtrue;
- }
- if (second ofclass SpellBook)
- "If a burin could write in a spell book, you wouldn't need
- the gnusto spell!";
- if (second ofclass Scroll)
- "You cannot write just anything on the magic parchment of
- a scroll: you can only ~copy~ a spell to it.";
- ];
-
- [ WriteOnSub; "Graffiti is banned."; ];
-
- [ CopyToSub;
- if (burin notin player) "You need to be holding the burin to copy a spell.";
- if (second ofclass SpellBook)
- "If a burin could write in a spell book, you wouldn't need
- the gnusto spell!";
- if (~~(second ofclass Scroll)) "You can only copy spells to scrolls.";
- if (child(second)~=0)
- "The scroll is already full of incantation.";
- "The scroll is not blank, only illegible.";
- ];
-
- ! ----------------------------------------------------------------------------
- ! Now the whole spell-casting system
- ! ----------------------------------------------------------------------------
-
- Attribute known_about; ! Player has seen this spell somewhere
- Attribute reversed; ! Effect of this known spell reversed
-
- Attribute is_spell;
- Class Spell
- with name "spell" "spells", article "the",
- number 0,
- word_name
- [; print (address) (self.&name)-->0;
- ],
- short_name
- [; self.word_name(); print " spell"; give self known_about; rtrue;
- ],
- specification
- [; self.short_name();
- print ": ", (string) self.purpose;
- ],
- before
- [; Examine: self.specification(); ".";
- ],
- has is_spell;
-
- Object memory
- with capacity 5,
- number_known 1,
- describe_contents
- [ i j k;
- objectloop (i in self) if (i.number==100) j++;
- if (j>0)
- { print "The ";
- objectloop (i in self)
- if (i.number==100)
- { k++; i.word_name();
- if (k==j-1) print " and ";
- if (k<j-1) print ", ";
- }
- if (j==1) print " spell is"; else print " spells are";
- print " yours forever. Other than that, y";
- }
- else print "Y";
- print "ou have ";
- j=0; k=0;
- objectloop (i in self) if (i.number<100) j++;
- if (j>0)
- { print "the ";
- objectloop (i in self)
- if (i.number<100)
- { k++;
- print (name) i;
- if (i.number==2) print " (twice)";
- if (i.number==3) print " (thrice)";
- if (i.number==4) print " (four times)";
- if (i.number>=5) print " (many times)";
- if (k==j-1) print " and ";
- if (k<j-1) print ", ";
- }
- }
- else print "no spells";
- " memorised.";
- ],
- learn_spell
- [ sp;
- if (sp.number==100) "You always know that spell.";
- print "Using your best study habits, you commit the ";
- sp.word_name();
- print " spell to memory";
- if (sp notin self) sp.number=0;
- move sp to self;
- self.number_known++;
- sp.number++;
- if (sp.number==1) print ".";
- if (sp.number==2) print " once again.";
- if (sp.number==3) print " a third time.";
- if (sp.number>3) print " yet another time.";
- if (self.number_known <= self.capacity) { new_line; rtrue; }
- self.forget_spell(sibling(child(self)));
- " You have so much buzzing around in your head, though,
- that it's likely something may have been forgotten
- in the shuffle.";
- ],
- forget_spell
- [ sp;
- if (sp notin self || sp.number==100) rtrue;
- self.number_known--;
- sp.number--;
- if (sp.number==0) remove sp;
- rtrue;
- ];
-
- Spell -> gnusto_spell
- with name "gnusto",
- purpose "copy a scroll into your spell book",
- number 100,
- magic
- [ i a_book;
- if (second ofclass SpellBook)
- "Unlike scrolls, spell books are magically guarded against
- the 'theft' of their lore.";
- if (second==0 || ~~(second ofclass Scroll))
- "Your spell fizzles vaguely out.";
- if (second notin player)
- "A gnusto spell would require close scrutiny of the scroll
- it is to copy: which you do not seem to be holding.";
- objectloop (i in player)
- if (i ofclass SpellBook) a_book=i;
- if (a_book==0)
- "Your spell fails, as you have no spell book.";
- i=child(second);
- if (i==0 || ~~(i ofclass Spell))
- { print_ret "Your spell fails, as ", (the) second,
- " is illegible.";
- }
- a_book.learn_spell(i); remove second;
- print_ret
- "Your spell book begins to glow softly. Slowly, ornately,
- the words of ", (the) i, " are inscribed,
- glowing even more brightly then the book itself.
- The book's brightness fades, but the spell remains!
- However, the scroll on which it was written vanishes as
- the last word is copied.";
- ];
-
- Class SpellBook
- with array_of_spells 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,
- capacity 16,
- learn_spell
- [ sp p i;
- p = self.&array_of_spells;
- for (i=0:i<self.capacity && (p-->i)~=0:i++) ;
- if (i==self.capacity) rtrue;
- p-->i = sp;
- ],
- before
- [; Open, Close:
- print_ret
- (The) self, " is always open to the right place, but it
- is also always closed. This eliminates tedious leafing and
- hunting for spells. Many lives have been saved by this
- magical innovation.";
- Attack:
- print_ret "When you are done, ", (the) self, " remains unmarred.";
- ],
- after
- [ p i j; Examine:
- p = self.&array_of_spells;
- for (i=0:i<self.capacity && (p-->i)~=0:i++)
- { j=p-->i; <Examine j>;
- }
- rtrue;
- ];
-
- Class Scroll
- with parse_name
- [ i j k; j=-1;
- if (self has general)
- { if (child(self)~=0 && child(self) ofclass Spell)
- j=(child(self).&name)-->0; else j='illegible';
- }
- for (::)
- { k=NextWord();
- if (k=='scrolls') parser_action=##PluralFound;
- if ((k=='scrolls' or 'scroll' or j) || k==(self.&name)-->0)
- i++;
- else return i;
- }
- ],
- before
- [ i; Examine:
- i=child(self);
- give self general;
- if (i==0 || ~~(i ofclass Spell))
- "The scroll has faded, and you cannot read it.";
- print "The scroll reads ~"; i.specification(); "~.";
- ],
- invent
- [; if (inventory_stage==2 && self has general)
- { if (child(self)==0 || ~~(child(self) ofclass Spell))
- print " (which is illegible)";
- else
- { print " (of ", (the) child(self), ")"; }
- }
- ];
-
- [ ReadableSpell i j k;
- if (scope_stage==1)
- { if (action_to_be==##Examine) rfalse;
- rtrue;
- }
- if (scope_stage==2)
- { objectloop (i in player)
- if (i ofclass SpellBook)
- { for (k=0:k<i.capacity && (i.&array_of_spells)-->k~=0:k++)
- { j=(i.&array_of_spells)-->k; PlaceInScope(j);
- }
- }
- rtrue;
- }
- ! No need for scope_stage 3 (the error stage), because our
- ! ParserError routine handles that case instead
- ];
-
- [ CopyableSpell i j k;
- if (scope_stage==1) return 1;
- if (scope_stage==2)
- { objectloop (i in player)
- if (i ofclass SpellBook)
- { for (k=0:k<i.capacity && (i.&array_of_spells)-->k~=0:k++)
- { j=(i.&array_of_spells)-->k; PlaceInScope(j);
- }
- }
- rfalse;
- }
- ! No need for scope_stage 3 (the error stage), because our
- ! ParserError routine handles that case instead
- ];
-
- [ SpellsSub; memory.describe_contents(); ];
-
- [ LearnSub; if (location==thedark)
- print "(The magic writing of the spells casts enough light
- that you can read them.)^";
- memory.learn_spell(noun);
- ];
-
- Global the_spell_was = gnusto_spell;
-
- [ CastOneSub; <Cast the_spell_was noun>; ];
-
- [ CastSub;
- the_spell_was = noun; memory.forget_spell(noun);
-
- if (noun has reversed)
- { give noun ~reversed;
- if (noun.unmagic() ~= 0) return;
- "Nothing happens.";
- }
-
- if (second ~= 0)
- { ResetVagueWords(second); ! Set "it", "him", "her"
- if (second provides before
- && second.before() ~= 0) return; ! Run before routine(s)
- }
- if (noun.magic() ~= 0) return;
- "Nothing happens.";
- ];
-
- [ InScope i;
- if (verb_word=='c,cast' or 'cast')
- objectloop (i in memory) PlaceInScope(i);
- rfalse;
- ];
-
- [ ParserError x i flag vb;
- if (etype==VERB_PE or ASKSCOPE_PE)
- { if (etype==ASKSCOPE_PE)
- { if (verb_word=='cast') vb=1;
- if (verb_word=='learn' or 'memorise' or 'memorize') vb=2;
- if (verb_word=='copy') vb=3;
- if (vb==0) { etype=CANTSEE_PE; rfalse; }
- }
- wn=verb_wordnum; if (vb~=0) wn++;
- x=NextWordStopped();
- for (i=player+1:i<=top_object:i++)
- if (i ofclass Spell && Refers(i,x)==1
- && i has known_about) flag=1;
- if (flag==1)
- { if (vb==0 or 1)
- "You haven't got that spell committed to memory. [Type ~spells~
- to see what you do remember.]";
- if (vb==2)
- "Your training is such that you can only memorise such a spell
- with the aid of a spell book containing it.";
- if (vb==3)
- "You have no text of that spell to copy.";
- }
- if (vb==1)
- "You haven't learned that spell, if indeed it is a spell.";
- if (vb==2 or 3)
- "You haven't access to that spell, if indeed it is a spell.";
- }
- rfalse;
- ];
-
- [ ChooseObjects obj code;
- if (code<2) rfalse;
- if (action_to_be==##WriteOn && obj in player) return 9;
- return 0;
- ];
-
- [ UnknownVerb word i;
- objectloop (i in memory)
- if (word==(i.&name)-->0) { the_spell_was = i; return 'c,cast'; }
- rfalse;
- ];
-
- [ PrintVerb v;
- if (v=='c,cast') { print "cast a spell at"; rtrue; }
- rfalse;
- ];
-
- ! ----------------------------------------------------------------------------
- ! And now, on with the story. First, some global variables:
- ! ----------------------------------------------------------------------------
-
- Global prepared_flag = false; ! Prepared for resurrection?
- Global hearing_good = false; ! Sharp hearing?
- Global number_filled = 0; ! Sockets in the temple filled
-
- ! ----------------------------------------------------------------------------
- ! A "questions" verb. Thus,
- ! "who is my friend helistar"
- ! "what was the great change"
- ! and so on are recognised.
- ! ----------------------------------------------------------------------------
-
- [ QuerySub;
- noun.description();
- ];
- [ Topic i;
- if (scope_stage==1) return 0;
- if (scope_stage==2)
- { objectloop (i ofclass Question) PlaceInScope(i);
- rtrue;
- }
- "At the moment, even the simplest questions confuse you.";
- ];
-
- Class Question;
- Question
- with name "helistar" "my" "friend" "colleague",
- description
- "Helistar is your colleague, an Enchanter like you who has been much
- on your mind lately. She has been investigating some very dark
- magic indeed, and seems not to be around any more. You feel rather
- vague about the details.";
- Question
- with name "magical" "magic" "burin",
- description "A burin is an engraving and writing tool.";
- Question
- with name "change" "great",
- description
- "Something you had a lot to do with, but what exactly? No, it's gone.";
- Question
- with name "cyclops",
- description
- "A one-eyed giant, usually hostile. (Don't they teach anything at
- adventurer school these days?)";
- Question
- with name "grue",
- description
- "The grue is a sinister, lurking presence in the dark places of the
- earth. Its favorite diet is adventurers, but its insatiable appetite
- is tempered by its fear of light. No grue has ever been seen by the
- light of day, and few have survived its fearsome jaws to
- tell the tale.";
- Question
- with name "grimoire",
- description
- "According to Chambers English Dictionary, a grimoire is ~a magician's
- book for calling up spirits~.";
- Question
- with name "spells" "work",
- description
- "Your memory is still dream-hazed, but it's coming back. As a trained
- Enchanter, you have the ability to cast spells like ~frotz~, provided
- you have learned them in advance. Some of these spells can be cast
- at something; others can be cast alone.
- ^^Spells are very complicated. Each time you cast one, you forget it
- (though you can get around this by learning it several times, so as
- to have several uses up your sleeve). The only way to hang on to
- a spell is to have it written down, on a scroll or in a spell book.
- Scrolls are not ideal for this, and you can only learn a spell from
- your spell book. (But you can add spells to your book.)
- ^^[Type ~learn frotz~ and then ~frotz coin~ for an example. You can
- also type ~spells~ to see what you currently have memorised.]";
-
- ! ----------------------------------------------------------------------------
- ! Some multiple objects, coins in fact, coded in deluxe fashion:
- ! ----------------------------------------------------------------------------
-
- Attribute is_coin;
- Class Coin
- with name "coin",
- description "A round unstamped disc, presumably part of the local
- currency.",
- parse_name
- [ i j w;
- if (parser_action==##TheSame)
- { if ((parser_one.&name)-->0 == (parser_two.&name)-->0) return -1;
- return -2;
- }
- w=(self.&name)-->0;
- for (::i++)
- { j=NextWord();
- if (j=='coins') parser_action=##PluralFound;
- else if (j~='coin' or w) return i;
- }
- ],
- has is_coin;
-
- Class GoldCoin
- class Coin,
- with name "gold",
- short_name "gold coin",
- plural "gold coins";
- Class SilverCoin
- class Coin,
- with name "silver",
- short_name "silver coin",
- plural "silver coins";
- Class BronzeCoin
- class Coin,
- with name "bronze",
- short_name "bronze coin",
- plural "bronze coins";
-
- SilverCoin players_coin;
-
- [ TossCoinSub; if (noun notin player) "You need to be holding the coin first.";
- move noun to parent(player);
- if (location==thedark) "You throw it away into the darkness.";
- if (random(20)==1)
- "You toss the coin, and it lands... on its edge, amazingly.";
- "You toss the coin, and it comes up... blank, since neither side is
- marked.";
- ];
-
- ! ----------------------------------------------------------------------------
- ! The player's spell book, and three initial spells (to go with gnusto):
- ! ----------------------------------------------------------------------------
-
- SpellBook players_book "spell book"
- with name "spell" "book" "my" "spellbook",
- description "My Spell Book^";
-
- Spell frotz_spell
- with name "frotz",
- purpose "cause an object to give off light",
- magic
- [; if (second==0) "There is a brief, blinding flash of light.";
- if (second has animate)
- "The spell, not designed for living creatures, goes sour.";
- if (second in compass)
- "The spell dissipates vaguely.";
- give second light;
- print_ret
- "There is an almost blinding flash of light as ", (the) second,
- " begins to glow! It slowly fades to a less painful level, but ",
- (the) second, " is now quite usable as a light source.";
- ],
- unmagic
- [; if (second==0) "There is a brief moment of deep darkness.";
- if (second has animate)
- "The spell, not designed for living creatures, goes sour.";
- if (second in compass)
- "The spell dissipates vaguely.";
- if (second hasnt light)
- print_ret (The) second, " isn't producing light as it is.";
- give second ~light;
- print_ret "A pool of darkness coagulates around ", (the) second,
- " but slowly fades back to normality. Still, ",
- (the) second, " is no longer any kind of light source.";
- ];
-
- Spell rezrov_spell
- with name "rezrov",
- purpose "open even locked or enchanted objects",
- magic
- [; if (second==0) "The world is open already.";
- if (second has animate)
- "It might be a boon to surgeons if it worked, but it doesn't.";
- if (second has open || second hasnt openable)
- "It doesn't need opening.";
- if (second hasnt locked)
- { give second open;
- print_ret (The) second, " opens obediently.
- Like swatting a fly with a sledge hammer, if you ask me.";
- }
- give second open ~locked;
- print "Silently, ", (the) second, " swings open. ";
- if (second has container) <<Search second>>; new_line; rtrue;
- ],
- unmagic
- [; if (second==0) "The world is closed already.";
- if (second has animate)
- "Happily, that is unnecessary.";
- if (second has locked || second hasnt lockable)
- "It doesn't need locking.";
- give second ~open locked;
- "Silently, ", (the) second, " swings shut and locks.";
- ];
-
- Spell yomin_spell
- with name "yomin",
- purpose "mind probe",
- magic
- [; if (second==0 || second hasnt animate)
- "That must be either vegetable or mineral.";
- if (second==player) "You give yourself a mild headache.";
- print_ret "You look into the rather ordinary thoughts of ",
- (the) second, ".";
- ],
- unmagic
- [; if (second==0 || second hasnt animate)
- "That must be either vegetable or mineral.";
- if (second==player) "You give yourself a mild headache.";
- print_ret (The) second, " is rather shocked, for some reason.";
- ];
-
- ! ----------------------------------------------------------------------------
- ! The first scene: the Hut and its (rather easy) secret
- ! ----------------------------------------------------------------------------
-
- Class Place
- has light;
-
- Place Hut "Ramshackle Hut"
- with description
- "Until quite recently, someone lived here, you feel sure.
- Now the furniture is matchwood and
- the windows are glassless. Outside, it is a warm, sunny day,
- and grasslands extend to the low hills on the horizon.",
- out_to Grasslands, w_to Grasslands,
- cant_go "There's only the one room: better go ~out~.",
- name "windows" "grasslands" "grass" "hills";
-
- Object -> furniture "wooden furniture"
- with name "furniture" "broken" "wood" "wooden",
- before
- [; Examine, Search, LookUnder:
- self.before=0; score=score+5;
- move h_box to player;
- "Searching through the furniture, which is good for nothing
- but firewood now, you come across an old cedarwood box,
- which you pick up for a closer look.";
- ],
- has scenery;
-
- Object h_box "cedarwood box"
- with name "cedar" "cedarwood" "wooden" "box",
- description "The box bears the calligraphed initial H."
- has container openable lockable locked;
-
- SpellBook -> helistars_book "Helistar's grimoire"
- with name "grimoire" "helistar" "helistars",
- description "This must be the grimoire of dangerous spells kept by
- your irresponsible friend Helistar. Many pages are
- missing, but a few spells remain:^",
- has proper;
-
- ! ----------------------------------------------------------------------------
- ! Grasslands and the valley
- ! ----------------------------------------------------------------------------
-
- Place Grasslands "Grasslands, near Hut"
- with name "grasslands" "grass" "hut" "path",
- description
- "The grasslands sway over low hills in all directions: it is a
- peaceful wilderness, broken only by this hut and a faint path
- to the north.",
- in_to Hut, e_to Hut,
- n_to Valley,
- cant_go "You wander around for a while but end up back at the hut.";
-
- Place Valley "Pocket Valley"
- with name "valley" "trail",
- description
- "A pleasant pocket valley in the grassy hills, through which a
- trail runs north-to-south.",
- n_to "The trail runs out to nothing, and you retreat for fear of
- getting so lost you couldn't find the hut again by nightfall.",
- cant_go "You wander around the pleasant valley, but are afraid to
- lose sight of the trail.",
- s_to Grasslands;
-
- [ RideSub; print_ret "You can hardly ride ", (a) noun, "."; ];
-
- Object -> horse "horse"
- with short_name
- [; if (self has general) print "winged horse";
- else print "chestnut horse";
- rtrue;
- ],
- parse_name
- [ i j; if (self has general) j='winged'; else j=-1;
- while (NextWord()==j or 'horse' or 'chestnut') i++;
- return i;
- ],
- describe
- [; print_ret
- "There is ", (a) self, " here, munching on a pile of oats.";
- ],
- before
- [; Cast: if (the_spell_was == bozbar_spell)
- { give self general;
- "A pair of handsome brown wings suddenly appears on
- the horse's powerful shoulders. The horse turns in a
- complete circle, a look of puzzlement on his face.";
- }
- if (the_spell_was == yomin_spell)
- "He is mainly thinking about oats. Partly who you are
- and what you're up to, but mainly oats.";
- Enter: <<Ride self>>;
- Ride: if (horse hasnt general)
- "You ride around for a while, exercising the horse, but
- soon enough he tires of this and pointedly brings you
- back to the oats. Obligingly you dismount and he
- begins grazing again.";
-
- print "You begin to ride north. Then, slowly at first but with
- increasing sureness, the horse begins beating its powerful
- wings. You rise majestically through the air, sailing
- gracefully across a chasm where the hills fall away.
- The horse lands gently on the far side and deposits you,
- taking to the skies again.^";
- PlayerTo(Edge); rtrue;
- ],
- has animate;
-
- Object -> oats "pile of oats"
- with name "oats" "pile" "of",
- before
- [; Examine, Search, LookUnder:
- self.before=NULL;
- move shiny_scroll to player; score=score+5;
- itobj=shiny_scroll;
- "Sifting through the oats, you find a shiny scroll! Lucky
- you got to it before the horse did. As you turn it over
- in your hands, it seems undamaged.";
- Take: "What would you want with all those oats?";
- ],
- has scenery;
-
- Scroll shiny_scroll "shiny scroll"
- with name "shiny";
-
- Spell -> bozbar_spell
- with name "bozbar",
- purpose "cause an animal to sprout wings",
- magic
- [; if (second==0 || second hasnt animate)
- "The spell dies away in vain.";
- if (second==player)
- "Your elbows twitch, but there is no other effect.";
- print_ret "For a moment, ", (the) second,
- " looks highly discomforted, but the moment passes.";
- ],
- unmagic
- [; if (second==0 || second hasnt animate)
- "The spell dies away in vain.";
- if (second==player) "What wings?";
- if (second==horse && horse has general)
- { give horse ~general;
- "The Enchanter giveth, and the Enchanter taketh away.
- The horse looks disconsolate but returns to the oats.";
- }
- print_ret (The) second, " has no wings to lose.";
- ];
-
- ! ----------------------------------------------------------------------------
- ! The Chasm and the snake
- ! ----------------------------------------------------------------------------
-
- Place Edge "Edge of Chasm"
- with name "wide" "chasm" "road" "daffodils" "clump",
- description
- "The road ends suddenly at a wide chasm. The road leads upward
- to the north, and you can see it continuing on the southern side
- of the chasm.",
- u_to Up_Road, n_to Up_Road,
- cant_go "The chasm is too perilous to approach. The only safe way is
- up and to the north.",
- before
- [; Jump: deadflag = true;
- "You jump bravely into the chasm, and plunge...
- gracefully through the air. (It gets a bit less noble and
- airy after that.)";
- ];
-
- Object -> snake "hissing snake"
- with name "hissing" "snake",
- initial
- "Lying in a tight coil at the edge of the chasm is a hissing snake.",
- description
- "It has some V-markings, some scaly parts, colours from grey to
- reddish-brown. Is that any help?",
- life
- [; "The snake hisses angrily!"; ],
- before
- [; Cast:
- switch(the_spell_was)
- { urbzig_spell:
- remove self;
- snakes_cube.initial =
- "Beside a clump of daffodils is a featureless white cube.";
- "The snake is replaced by a clump of daffodils.";
- bozbar_spell:
- deadflag = true; remove self;
- snakes_cube.initial =
- "A featureless cube rests where the snake took off from.";
- "The snake is transformed into a huge, winged serpent,
- a dragon which bellows and leaps out into the chasm,
- backwinging furiously... and knocking you over the
- edge quite by accident.";
- yomin_spell:
- "Horrid reptilian thoughts insinuate their way into you.";
- }
- Take, Remove:
- "The slipperiness of its skin is only one of many reasons
- why this is ill-advised.";
- ],
- has animate;
-
- FeaturelessCube -> snakes_cube "cube"
- with initial
- "The snake appears to be curled around a featureless white cube.",
- before
- [; if (snake notin nothing) "The snake won't let you near that cube!";
- ];
-
- ! ----------------------------------------------------------------------------
- ! The crest of the hill; Icarus the tortoise; the chewed scroll
- ! ----------------------------------------------------------------------------
-
- Place Up_Road "Crest of Hill"
- with description
- "The road crosses the top of a ridge here, sloping downwards to
- the south and the northwest. A track diverges to east.",
- nw_to Cave_Mouth, s_to Edge, d_to Edge, e_to Track;
-
- Object -> tortoise "tortoise"
- with name "tortoise" "turtle",
- initial "A tortoise ambles along the road, extremely slowly.",
- life
- [; "The tortoise (slowly) turns its neck to look at you (stupidly).";
- ],
- before
- [; Cast: switch(the_spell_was)
- { urbzig_spell:
- "Just how safe do you want your surroundings to be?";
- bozbar_spell:
- move chewed_scroll to parent(self); remove self;
- StartDaemon(self); score=score+5;
- "The tortoise seems to be incapable of expressing
- surprise, but is now soaring away high in the sky.
- Something rather grubby is left behind.";
- yomin_spell:
- "For a moment you think there is nothing there, as you
- chew absentmindedly on a leaf. But somewhere inside
- the tortoise is a sense of wonder at the amazing blue
- canopy of the sky.";
- }
- Take, Remove:
- "Your parents always warned you not to pick up casual
- acquaintances met on the road.";
- ],
- daemon
- [ i; if (location ~= Up_Road or Track || random(6)~=1) rfalse;
- if (random(4)==1 && self hasnt general)
- { move feather to location; give self general;
- "^A tortoise-feather flutters to the ground before you!";
- }
- i=random(3);
- switch(i)
- { 1: print "^High in the sky,";
- 2: print "^Far above you,";
- 3: print "^Tiny in the blue sky,";
- }
- " a tortoise flaps across the sun.";
- ],
- has animate;
-
- Scroll torn_scroll "torn scroll"
- with name "torn";
-
- Spell -> lobal_spell
- with name "lobal",
- purpose "sharpen hearing",
- magic
- [; if (second==0 || second hasnt animate)
- "There is a loud bang in your ear, but no other effect.";
- if (second==player)
- { if (hearing_good) "There is no further effect.";
- hearing_good=1; StartTimer(self, 5);
- "Nothing happens, possibly because those butterflies on the
- other side of the hill keep distracting you.";
- }
- print_ret (The) second,
- " is no doubt grateful for the gift of sharper hearing.";
- ],
- unmagic
- [; if (second==0 || second hasnt animate)
- "There is a brief silence, but no other effect.";
- if (second==player) { StopTimer(self); hearing_good=0; "Pardon?"; }
- print_ret (The) second,
- " is no doubt grateful not to have to listen to you.";
- ],
- time_left 0,
- time_out
- [; if (hearing_good)
- { hearing_good = false;
- "^Those wretched butterflies finally shut up.";
- }
- ];
-
- Scroll chewed_scroll "chewed scroll"
- with initial "It looks as if the tortoise was eating something - once
- it might have been a scroll, but now it lies there,
- chewed up like a lettuce leaf.",
- before
- [; Cast: if (the_spell_was == caskly_spell)
- { move torn_scroll to parent(self);
- remove self; score=score+5;
- "Before your eyes, the scroll begins to repair itself,
- failing only at the very last tear. Not quite perfect
- perhaps, but certainly a readable, if torn scroll.";
- }
- Eat: "~Eating your words~ is notoriously dangerous for a wizard.
- Rearranged in the stomach, a spell might do anything!";
- ],
- with name "chewed";
-
- Object feather "tortoise feather"
- with name "tortoise" "feather",
- description
- "Possibly your rarest, and also least valuable, possession.";
-
- ! ----------------------------------------------------------------------------
- ! The cave mouth and the perfect sapphire
- ! ----------------------------------------------------------------------------
-
- Place Cave_Mouth "Cave Mouth"
- with name "gorse" "footpath" "cave" "mouth",
- description
- "This is a cave mouth, at one end of a road which winds southeast
- over rising ground. The entrance west to the caves is a dark
- tunnel, and only a footpath runs further north, into gorse.",
- u_to Up_Road, se_to Up_Road, in_to Iron_Door, w_to Iron_Door,
- n_to Footpath;
-
- Object -> Iron_Door "iron door"
- with name "iron" "door" "heavy",
- description "It just looks like an ordinary heavy iron door.",
- door_dir
- [; if (location==Cave_Mouth) return w_to; return e_to;
- ],
- door_to
- [; if (location==Cave_Mouth) return In_Cave;
- return Cave_Mouth;
- ],
- describe
- [; if (self has open) "^The iron door stands open.";
- if (self hasnt locked) "^The iron door is unlocked but shut.";
- "A heavy iron door bars the cave mouth.";
- ],
- found_in In_Cave Cave_Mouth
- has static door openable locked lockable;
-
- ! Cf. T. S. Eliot, "Burnt Norton" II:
- ! (but see also Mallarme's sonnet from which Eliot borrowed the image)
-
- Object -> sapphire "perfect sapphire"
- with name "perfect" "sapphire" "gemstone" "gem",
- initial "Clotted in the mud beside the door is a perfect sapphire.",
- before
- [; Examine: remove self; move caskly_spell to memory;
- players_book.learn_spell(caskly_spell);
- caskly_spell.number=100;
- "As you gaze into the perfect blue of the sapphire,
- you feel your mind begin to reel. Unable to bear
- the naked sight of perfection, you look away, ashamed.
- As you do so, the sapphire cracks and wastes away to
- thin hot dust. But something remains, something in your
- mind...";
- ];
-
- Spell caskly_spell
- with name "caskly",
- purpose "cause perfection",
- magic
- [; if (second==0) "Trying to make everything perfect was a little
- too ambitious.";
- if (second==player) "Oh, don't be too hard on yourself.";
- if (second==helistars_book)
- "Your spell is not powerful enough to restore the lost pages.";
- print_ret (The) second, " looks pretty perfect as is.";
- ];
-
- ! ----------------------------------------------------------------------------
- ! Inside the Cave, the powerful urbzig spell and its consequences
- ! ----------------------------------------------------------------------------
-
- Place In_Cave "Inside Cave"
- with description
- "A wide but shallow cave not far inside the hill. There is no
- obvious exit, except for the way you came in.",
- out_to
- [; if (CoinsIn(left_pan)+CoinsIn(right_pan) < 6)
- "Something bars your way, and you hear
- the scales jangling militantly. You were trying to
- steal its coins!";
- if (scales.number~=0) "Something bars your way, and you hear
- the scales jangle slightly with energy.";
- return Iron_Door;
- ],
- e_to
- [; return self.out_to();
- ],
- cant_go "The only way is back ~out~ through the iron door.",
- after
- [; Take: if (parent(noun)==left_pan or right_pan)
- print_ret "Taken from ", (the) parent(noun), ".";
- ],
- has ~light;
-
- FeaturelessCube -> cave_cube "cube"
- with initial "Balanced on a rock formation is a featureless white cube.";
-
- Object -> scales "pair of scales"
- with name "pair" "of" "scales" "pans", number 0,
- describe
- [; print "^A fair-sized pair of scales hangs from a bracket in the
- cave wall. ";
- if (self.number==0) "The scales are balanced.";
- if (self.number==1) "The left-hand side is higher.";
- "The right-hand side is higher.";
- ],
- before
- [; "There are left and right hand pans, which you should refer to
- individually.";
- ],
- has static supporter;
-
- Class ScalePan
- with name "pan" "side" "tray",
- before
- [; Receive:
- if (noun ofclass Scroll or Coin) rfalse;
- if (noun==feather) rfalse;
- "The pans gleam with what almost seems greed, and somehow they
- contrive to nudge your hand past them with your worthless and
- boring item.";
- ],
- after
- [ i j d w1 w2; Receive, LetGo: i=scales.number;
- objectloop (j in left_pan) w1=w1 + WeightOf(j);
- objectloop (j in right_pan) w2=w2 + WeightOf(j);
- if (w1==w2) scales.number=0;
- if (w1 > w2) scales.number=-1;
- if (w1 < w2) scales.number=1;
- j=scales.number; d=(w2-w1)*(scales.number);
- if (j==i) rfalse;
- if (j==0) "The scales come into balance.";
- if (j==1) print "The left pan "; else print "The right pan ";
- if (d==1) "very slowly rises up.";
- "rises up.";
- ],
- has supporter scenery;
-
- [ WeightOf obj;
- if (obj==bronze_coin) return 2;
- if (obj ofclass Scroll || obj==feather) return 1;
- return 3;
- ];
-
- [ CoinsIn obj i c;
- objectloop (i in obj) if (i ofclass Coin) c++;
- return c;
- ];
-
- ScalePan -> right_pan "right pan" with name "right";
- GoldCoin -> ->;
- GoldCoin -> ->;
- GoldCoin -> ->;
-
- ScalePan -> left_pan "left pan" with name "left";
- BronzeCoin -> -> bronze_coin;
- GoldCoin -> ->;
- GoldCoin -> ->;
-
- Scroll -> -> crumpled_scroll "crumpled scroll"
- with name "crumpled";
- Spell -> -> -> urbzig_spell
- with name "urbzig",
- purpose "turn a dangerous object into a harmless one",
- magic
- [; if (second==0) "The spell fizzles away.";
- if (second==player) "It's a matter of opinion, isn't it?";
- if (second==helistars_book or mace || second ofclass FeaturelessCube)
- { CDefArt(second); remove second;
- if (second==mace && cyclops in location)
- { remove cyclops; move eye_cube to location;
- " turns into a featureless white cube just as the cyclops
- was about to hit you with it. Mightily embarrassed
- by this, he drops the cube and runs off!";
- }
- print " turns into a moth and flutters away.^";
- rtrue;
- }
- print_ret "Nothing obvious happens. Perhaps ", (the) second,
- " isn't so very dangerous after all.";
- ],
- unmagic
- [; if (second==0) "The spell fizzles away.";
- if (second==player) "It's a matter of opinion, isn't it?";
- if (second has static || second has scenery)
- { print_ret "Your spell is too weak for something quite as
- monumentally harmless as ", (the) second, ".";
- }
- if (second==helistars_book or snake or cyclops or mace
- || second ofclass FeaturelessCube)
- "Nothing obvious happens.";
- if (second in player)
- { remove second; deadflag = true;
- "Suddenly, a tarantula races up your arm to your throat!
- Perhaps it was unwise to gizbru something you were
- actually holding.";
- }
- if (cyclops has general)
- "Nothing happens. Perhaps that's just as well,
- after the last time.";
- move cyclops to location;
- remove second; give cyclops general; StartTimer(cyclops, 5);
- print_ret (The) second, " is replaced by a buck-toothed cyclops
- wielding a mace!";
- ];
-
- Object cyclops "buck-toothed cyclops"
- with name "buck" "toothed" "buck-toothed" "cyclops",
- initial "A huge buck-toothed cyclops menaces you, armed with a
- heavy mace!",
- before
- [; Cast: if (the_spell_was == bozbar_spell)
- "Does the term ~death wish~ mean anything to you?";
- if (the_spell_was == urbzig_spell)
- "The cyclops bellows with glee as your spell has
- no effect. (After all, he wouldn't be ~dangerous~ if
- an urbzig spell worked on him, would he?)";
- ],
- life [; "He roars incoherently, swinging the mace!"; ],
- time_left 0,
- time_out
- [; if (self notin location)
- { remove self; rtrue;
- }
- deadflag = true; remove mace; remove cyclops;
- "Feeling that he's given you quite long enough to explain why
- you made such a mess of his life, he swings the great mace
- maniacally down on you!";
- ],
- each_turn
- [ i; i=random(4); if (i==1) "^The cyclops leaps and bellows!";
- if (i==2)
- "^Whirling the mace, the cyclops jabbers at you incoherently.";
- if (i==3)
- "^The cyclops is losing patience (the appropriate cyclops
- word is untranslatable into English, but approximately means
- ~forbearance in not smashing all nearby skulls~).";
- "^The cyclops jabs you with the mace, almost breaking your rib.";
- ],
- has animate transparent;
-
- Object -> mace "mace"
- with name "heavy" "mace" "axe",
- description "It looks much too heavy for you to even lift.";
-
- FeaturelessCube -> eye_cube "cube"
- with initial
- "A featureless white cube lies where the cyclops dropped it.";
-
- ! ----------------------------------------------------------------------------
- ! The Footpath and the carpet
- ! ----------------------------------------------------------------------------
-
- Place Footpath "Gorse Bushes"
- with description
- "The footpath from the cave mouth runs into dense, impenetrable
- gorse bushes. Perhaps it wasn't so much a footpath as a rill
- in the earth where roots wouldn't take; anyway, there's no way
- but back south.",
- s_to Cave_Mouth;
-
- Object -> carpet "beautiful red carpet"
- with name "beautiful" "magic" "red" "carpet",
- initial
- "Slung over one of the gorse bushes is a beautiful red carpet.",
- description
- "This is a carpet of unusual design. It is red, beautifully woven
- and bears a pattern of cubes.",
- before
- [ i; Receive:
- if (self notin location || self hasnt moved)
- "Not until the carpet's on the ground, you can't.";
- Ride: <<Enter self>>;
- Enter:
- if (self notin location || self hasnt moved)
- "Not until the carpet's on the ground, you can't.";
- if (location==Balance_Room)
- "Mysteriously, the carpet rucks and pulls until you're
- thrown off. It settles back on the white floor with a
- contented sigh.";
- if (location==In_Cave)
- "The carpet rises suddenly, crashing into the roof of
- the cave and throwing you back off again. Painfully.";
- if (location==Bazaar) i=Up_Road; else i=Bazaar;
- print "The carpet rises suddenly into the fluffy white
- clouds, and after a headlong journey deposits you...^";
- move self to i;
- PlayerTo(i,1); move player to self; <<Look>>;
- Take: if (player in self) "Not while you're on it!";
- for (i=child(self):i~=0:i=child(self))
- { move i to location;
- print "(Dislodging ", (the) i, ")^";
- }
- ],
- has supporter enterable;
-
- ! ----------------------------------------------------------------------------
- ! A Bazaar Lottery
- ! ----------------------------------------------------------------------------
-
- Global last_called = 1;
- Global explicit_flag = 0;
- Global tickets_taken = 0;
-
- Class Ticket(6)
- with number -1, name "ticket",
- description
- [; if (self.number==2306) "It is labelled ~First Prize~!";
- if (self.number==5802) "It is labelled ~Nineteenth Prize~.";
- "~You lose,~ says the ticket, with a smily face. ~Try again!~";
- ],
- short_name
- [; if (self.number==-1) rfalse;
- print "lottery ticket ", self.number; rtrue;
- ],
- parse_name
- [ i j w;
- i=0;
- if (NextWord()=='lottery') i++; else wn--;
- if (NextWord()=='tickets')
- { parser_action=##PluralFound; return i+1; } else wn--;
- if (NextWord()~='ticket') return 0;
- i++;
- w=TryNumber(wn);
- if (w==-1000) { explicit_flag = false; return i; }
- if (w==0) return 0;
- if (self.number==-1)
- { objectloop(j ofclass Ticket)
- if (w == j.number) return 0;
- }
- else
- { if (self.number~=w) return 0;
- }
- i++; last_called = w; explicit_flag = true; return i;
- ],
- before
- [; Examine:
- if (self in board)
- "It would be cheating to see what's written on the curled up
- tickets still in the board.";
- Cast: "~Get outta here, bub!~, the barker says, disgusted.";
- ];
-
- Place Bazaar "Crowded Bazaar"
- with description
- "This is a crowded, noisy bazaar. Directly in front of you is
- a lottery! But the contemptuous-looking barker is doing a
- very poor trade: hardly anyone wants his first prize, the
- big cuddly toy elephant, or even his nineteenth prize, a
- featureless white cube.",
- each_turn
- [; switch(random(4))
- { 1: "^~Roll up! Roll up! One silver piece for three goes!~";
- 2: "^~Come on, then! Just a silver coin gets you three!~";
- 3: "^~Think what you could win, all for one silver coin!~";
- 4: "^~This could be your lucky day!~";
- }
- ],
- before
- [; Learn:
- "~None of that!~ snaps the barker angrily, putting you off
- your study habits. He mutters about ~Enchanter cheats~,
- but under the circumstances you decide to let the insult
- pass.";
- ],
- cant_go "Everywhere, the crowds of jabbering natives block your way
- to all the good stalls. In fact, the only one you can get at is
- this dismal lottery.";
-
- Object -> board "lottery board"
- with credit 0,
- name "board" "lottery" "holes",
- description
- "There are a hundred holes each way, making, um, let's see, yes,
- ten thousand tickets in all. Still, there are nineteen prizes,
- so your odds must be, oh, well, not too awful anyway.",
- before
- [ i; LetGo:
- if (self.credit == 0)
- "The barker stabs you in the chest with
- his finger. ~That's a silver coin to you, bub!~";
-
- if (explicit_flag)
- { objectloop (i ofclass Ticket)
- if (last_called == i.number)
- "That ticket's already taken.";
- }
- else
- { .RandomChoice;
- last_called = random(10000);
- objectloop (i ofclass Ticket)
- if (last_called == i.number)
- jump RandomChoice;
- }
-
- tickets_taken++;
- self.credit--;
-
- i = Ticket.create();
- if (i == 0)
- "The barker looks metaphysically embarrassed. ~Um,
- Inform's object creation system seems not to have worked.~";
-
- i.number = last_called; itobj = i;
-
- move i to player; give i moved proper;
- if (explicit_flag==0)
- print "Randomly picking from the ", 10001-tickets_taken,
- " numbered holes with tickets in, you ";
- else print "You ";
- print_ret "take ", (the) i, " out of the board.";
-
- Examine: ;
- Receive:
- if (noun ofclass Ticket)
- "~No changes of mind, that's your ticket now! Give it to
- me if you want to play it.~";
- <<Push self>>;
- default:
- "The barker is burly, and won't let you
- tamper with the board.";
- ],
- initial
- "Behind the barker is a huge drilled board, and inside each little
- numbered hole is a rolled-up lottery ticket."
- has static container open;
-
- Ticket -> -> ticket_in_board "rolled-up ticket from the board"
- with article "a";
-
- Object -> barker "barker"
- with name "barker" "burly" "man",
- number 0,
- description
- "A boxer gone to seed who failed as a magician all down the
- coast, that'd be your guess.",
- life
- [; Attack, Kiss: "No way. He must weigh twice what you do.";
- Ask: switch(noun)
- { 'prize', 'prizes':
- "~Just one silver coin and a prize could be yours!~";
- 'white', 'featureless', 'cube':
- "He blows the dust off it. ~Genuine antique, that.~";
- 'elephant', 'toy', 'cuddly':
- "~Good quality merchandise,~ he says, in a way that
- suggests he can only spell one of those three words.";
- 'ticket', 'tickets', 'lottery':
- "~Three tickets for one silver coin!~";
- default: "~Just play the game, bub.~";
- }
- Order, Answer: "The barker glowers at you.";
- Give: if (noun ofclass Ticket)
- { remove noun;
- if (noun.number==2306)
- { move elephant to player; give elephant moved;
- remove pelephant;
- Bazaar.description =
- "This is a crowded, noisy bazaar. Directly in front of you is
- the lottery!";
- "With very bad grace, the barker shoves the
- cuddly toy elephant into your arms.";
- }
- if (noun.number==5802)
- { move barker_cube to player; give barker_cube moved;
- remove pcube;
- Bazaar.description =
- "This is a crowded, noisy bazaar. Directly in front of you is
- the lottery!";
- score=score+5;
- "With concealed relief, the barker shoves the
- featureless white cube into your hands.";
- }
- "~Bad luck! You lose!~";
- }
- if (self.number==2) "~You've had enough goes already!~ he
- growls. No wonder trade is bad.";
- if (~~(noun ofclass Coin))
- "~What do you call that? One silver coin to play!~";
- if ((noun.&name)-->0 == 'bronze')
- "~Bronze! Not a chance, sunshine.~";
- remove noun;
- board.credit = board.credit + 3;
- self.number++;
- if ((noun.&name)-->0 == 'gold')
- "Gleefully the barker snatches the gold coin. ~Sorry
- bub, no change. Business is slack today!~";
- "Grudgingly the barker takes the silver coin and stands
- back to let you at the board, arms folded.";
- ],
- before
- [; Cast: switch(the_spell_was)
- { bozbar_spell:
- "He's not that much of an animal.";
- lobal_spell:
- "His problem is listening, not hearing.";
- caskly_spell:
- "For a moment his hair seems to comb itself.
- Irritated, he ruffles it again, and the spell dies
- an ignominious death.";
- yomin_spell:
- if (elephant has moved || barker_cube has moved)
- "The barker's mind is a heap of grumbles about lost
- prizes and scrawny Enchanters.";
- if (self hasnt general)
- { give self general;
- "~Hope that scrawny Enchanter doesn't pick 2306!~
- thinks the barker (slowly).";
- }
- "~If that mark does win, hope it's only worthless
- old 5802,~ ponders the barker.";
- }
- ],
- has animate scenery;
-
- Object -> prizes "prizes"
- with name "prize" "prizes",
- before [; "~Hands off those prizes!~"; ],
- has scenery;
-
- Object -> pelephant "prize elephant"
- with name "prize" "elephant" "cuddly" "toy",
- description "Pink, cuddly, toy, elephant. Says it all, really.",
- before [; Examine: ; default: "~Hands off those prizes!~"; ],
- has scenery;
-
- Object -> pcube "prize cube"
- with name "prize" "featureless" "white" "cube",
- description "Wouldn't you like to win it?",
- before [; Examine: ; default: "~Hands off those prizes!~"; ],
- has scenery;
-
- Object elephant "cuddly toy elephant"
- with name "cuddly" "toy" "elephant",
- description "Pink, cuddly, toy, elephant. Says it all, really.",
- before
- [; Cast: if (the_spell_was == bozbar_spell)
- "Let me get this straight. You, the enchanter who
- defeated Krill, the head of the Borphee Guild
- himself... are attempting to grow wings on a pink
- cuddly elephant?";
- if (the_spell_was == yomin_spell) "Woolly.";
- ];
-
- FeaturelessCube barker_cube "cube";
-
- ! ----------------------------------------------------------------------------
- ! The spells in Helistar's grimoire
- ! ----------------------------------------------------------------------------
-
- Spell lleps_spell
- with name "lleps",
- purpose "reverse effect of memorised spell",
- magic
- [; if (second==0 || second notin memory)
- "The spell backfires, painfully.";
- if (second.number==100)
- "You know that spell too well for your mind to be able
- to accept the change.";
- if (second has reversed) give second ~reversed;
- else give second reversed;
- if (second==lleps_spell)
- { memory.forget_spell(second);
- "Your mind wrenches as the two lleps spells
- cancel each other out, leaving only a sensation
- quite like a hangover.";
- }
- print_ret "Your mind wrenches as ", (the) second,
- " reverses itself.";
- ],
- unmagic
- [; return self.magic(); ! The reverse of "lleps" is "lleps"
- ];
-
- Spell mortin_spell
- with name "mortin",
- purpose "cause immediate death of caster",
- magic
- [; deadflag = true;
- "You really can't fault Helistar on this one. Death is
- absolutely immediate, like a sudden blackout curtain...";
- ],
- unmagic
- [; prepared_flag = true;
- "Nothing quite happens... and yet you feel enormously more
- confident as you go about this dangerous world.";
- ];
-
- ! ----------------------------------------------------------------------------
- ! Death and the Boneyard
- ! ----------------------------------------------------------------------------
-
- [ AfterLife;
- if (~~prepared_flag) rfalse;
-
- if (player in Balance_Room)
- "^^Your foresight in preparing a resurrection was wasted. The
- tangled magic of the Balance Room coiled around your puny
- enchantment like a constricting serpent.";
-
- prepared_flag = false; deadflag = false; hearing_good = false;
-
- if (memory.capacity >= 2) memory.capacity--;
-
- while (child(player)~=0) move child(player) to parent(player);
- move players_book to player;
-
- print "^^With great foresight you prepared yourself for resurrection...
- Your mind feels a little weaker, but at least you're alive.^";
- PlayerTo(Boneyard);
- ];
-
- Place Boneyard "Boneyard"
- with name "bones" "blades" "shoulder" "skulls",
- description
- "This is a room of bones. Shoulder blades make up the floor,
- skulls the walls and leg-bones the door frames. The west exit
- leads into darkness, but the doorway to the north opens onto a
- seemingly normal scene.",
- n_to
- [; if (scales.number ~= 0) return In_Cave;
- return Grasslands;
- ],
- w_to "Some magical force blocks your way, as though that doorway
- led into adventures from your past which you cannot rejoin now.",
- before
- [; Examine, Search:
- if (noun==w_obj) "You can make out nothing to the west.";
- ];
-
- Scroll -> worthless_scroll "worthless scroll"
- with initial "You are almost treading on a worthless scroll.",
- name "worthless";
-
- Spell -> -> filfre_spell
- with name "filfre",
- purpose "produce gratuitous fireworks",
- magic
- [; if (self hasnt scored) { score++; give self scored; }
- "A brief shower of gratuitous fireworks spells out:
- ^^The masterly Enchanter trilogy was written by Marc Blank,
- Dave Lebling and Steve Meretzky.";
- ],
- unmagic
- [; "A lengthy shower of artistically justified fireworks spells out:
- ^^The masterly Enchanter trilogy was written by Jane Austen,
- Emily Bronte and Edgar Allen Poe.";
- ];
-
- ! ----------------------------------------------------------------------------
- ! The Cubical Temple
- ! ----------------------------------------------------------------------------
-
- Place Track "Track, outside Temple"
- with description
- "This is the end of a long track winding through desolate hills,
- which runs back west up to the ridge.",
- before
- [; Listen:
- if (~~hearing_good) "The chanting is too quiet to make out.";
- "The endlessly repeating threnody of the monks tells of
- the legend of one who will some day enlighten their order,
- and so be taken up to a higher plane. He (or she,
- presumably) is known as The Four-Cubed One.";
- ],
- w_to Up_Road, u_to Up_Road;
-
- Object -> Temple "cubical Temple"
- with name "temple" "cubical" "cube" "enormous",
- before
- [ i j;
- Enter: "The Temple is featureless and unbroken. Perhaps the top
- is open, because the sound must come from somewhere...
- but you wouldn't bet on it.";
- Cast: switch(the_spell_was)
- { rezrov_spell:
- "The huge temple remains impassive at your relatively
- puny enchantment.";
- frotz_spell:
- objectloop (i in player)
- if (i ofclass FeaturelessCube) j++;
- if (j==0)
- "The temple shakes, but then is still again.";
- if (j<4) "The temple shakes! White light plays
- over your hands and possessions, but then all is
- still again.";
- print "The temple shakes and white light bathes you.
- Smoothly it unfolds itself in a four-dimensional
- way your senses can barely comprehend. All you
- know is that when it is over,
- you find yourself in...^";
- hearing_good = false; score=score+5;
- PlayerTo(Balance_Room); rtrue;
- }
- ],
- describe
- [; print "^You stand outside an enormous temple in the shape of a
- perfect, featureless white cube, four hundred feet on a
- side. From somewhere within you hear the ";
- if (hearing_good) print "bellowing noise";
- else print "tiny sound";
- " of the monks chanting.";
- ],
- description
- "It's much like every other gigantic temple in the shape of a
- featureless white cube you've ever seen. No obvious way in.",
- has static;
-
- ! ----------------------------------------------------------------------------
- ! Inside the Temple
- ! ----------------------------------------------------------------------------
-
- Place Balance_Room "Balance Room"
- with description
- "This seems to be the inside of a featureless white cube, forty
- feet on a side. The air is stale and there is no exit.";
-
- Object -> balance_meter "image of the scales"
- with name "image" "scales" "of" "pair", article "the",
- initial "The image of a pair of scales hangs high in the air. One
- pan is much lower than the other.",
- before
- [; "It's only an image.";
- ],
- has static;
-
- Object -> dusty_podium "dusty podium"
- with name "podium" "dusty" "cobwebs" "cobwebbed",
- initial "Far below the scales, in the centre of the ~floor~, is a
- predictably-shaped podium, but it is so dusty and
- cobwebbed that you can't see what it once was.",
- before
- [; Cast: if (the_spell_was == caskly_spell)
- "Nice try, but it is protected from enchantment.";
- "However dusty it is, the podium is still protected from
- casual enchantment.";
- Rub: remove self; move balance_key to Balance_Room;
- itobj = balance_key;
- "No substitute for old-fashioned hard work, sometimes,
- and after much patient (sneezy) scrubbing, the podium
- appears in its true white glory. Set into it are four
- sockets, arranged in a two by two square.";
- ],
- has static;
-
- Object balance_key "podium"
- with name "podium" "pedestal" "platform" "cubical",
- description "As predicted, it is cubical.",
- initial "Far below the scales, in the centre of the ~floor~, is a
- predictably-shaped podium. Set into it are four sockets,
- arranged in a two by two square.",
- has static supporter;
-
- Object -> sockets "two by two square"
- with name "square" "two" "by" "two",
- before
- [ i; if (action~=##Examine || number_filled==0)
- "You'll have to say which socket you mean.
- (Let's call them ~top left~, ~bottom right~ and so on.)";
- objectloop (i in self)
- { print (The) i;
- if (child(i)==0) print " is empty.^";
- else { print " contains ", (a) child(i), ".^"; }
- }
- rtrue;
- ],
- has static;
-
- Class Socket
- with name "socket", article "the",
- before
- [; Cast: "The sockets are proof against magic.";
- Examine: print (The) self, ", cubical and slightly more
- than four inches on a side, is decorated with ",
- (string) self.description;
- if (child(self) == nothing) ".";
- print_ret ", and contains ", (a) child(self), ".";
- Receive: if (~~(noun ofclass FeaturelessCube))
- "The socket rejects that.";
- if (child(self) ~= nothing)
- "There is already a cube in that socket.";
- ],
- after
- [; LetGo: number_filled--;
- "With much struggle, you manage to pull the cube away.";
- Receive: number_filled++;
- if (number_filled==4)
- { if (snakes_cube in bl_socket
- && barker_cube in ul_socket
- && cave_cube in br_socket
- && eye_cube in ur_socket)
- { deadflag=2; score=score+5;
- "As you place the final cube into the sockets, you feel
- imbued with celestial wisdom (more so than usually).
- You find yourself growing to the height of the cube, so
- that you pull the balances back level by hand, and then
- you grow still further, out of the temple until it is but
- a cube in your hand, and you are a giant towering over
- the land.
- ^^Then, of course, you wake up, glumly realising it's time
- to go to your job at the new Borphee Laboratories and
- all those Wheatstone bridge experiments. But at least
- you can dream about the old days.";
- }
- "The sockets are all full now, but that doesn't mean
- anything's happened.";
- }
- "The cube is a predictably perfect fit in the socket.";
- ],
- has static container open;
-
- Socket -> bl_socket "bottom left socket"
- with name "bottom" "left" "serpent",
- description "a serpent";
-
- Socket -> ul_socket "top left socket"
- with name "top" "left" "bazaar",
- description "a scene in a bazaar";
-
- Socket -> br_socket "bottom right socket"
- with name "bottom" "right" "cave",
- description "an engraving of a rocky cave";
-
- Socket -> ur_socket "top right socket"
- with name "top" "right" "eye",
- description "an eye";
-
- ! ----------------------------------------------------------------------------
- ! That's all of the object definitions: just a little code and grammar left
- ! ----------------------------------------------------------------------------
-
- [ Initialise;
-
- location = Hut;
- move burin to player;
- move players_coin to player;
- move players_book to player;
-
- thedark.description =
- "It is pitch black. You are likely to be eaten by a grue.";
- ! (In fact you are stone-cold certain not to be, but never mind.)
-
- players_book.learn_spell(gnusto_spell);
- players_book.learn_spell(frotz_spell);
- players_book.learn_spell(yomin_spell);
- players_book.learn_spell(rezrov_spell);
-
- helistars_book.learn_spell(frotz_spell);
- helistars_book.learn_spell(lleps_spell);
- helistars_book.learn_spell(mortin_spell);
-
- give gnusto_spell known_about;
-
- "^^^^^[Welcome to a short story called ~Balances~, one of the example
- games for the Inform design system. Some people may recognise the
- setting, but others might like to type ~how do spells work~ -
- the game responds to a few such questions.]
- ^^You feel a little confused as to how you got here. Something
- to do with Helistar! That's right, and how the world is so far
- off balance nowadays, after the Great Change.^^";
- ];
-
- [ PrintRank;
- print ", earning you the rank of ";
- if (score >= 50) "Scientist.";
- if (score >= 40) "Spellbreaker.";
- if (score >= 30) "Sorcerer.";
- if (score >= 20) "Enchanter.";
- if (score >= 10) "novice Enchanter.";
- "lost dreamer.";
- ];
-
- [ DiagnoseSub;
- switch(memory.capacity)
- { 5: "You feel fine, and your memory is unimpaired.";
- 4: "You feel shaky after your brush with death, but your mental
- faculties seem sound.";
- 3: "For someone who has died twice, you're in reasonable shape.";
- }
- "How many times have you died now? Your memory isn't what it was.";
- ];
-
- ! ----------------------------------------------------------------------------
- ! Grammar extensions needed by the spell-casting and cube-writing rules:
- ! ----------------------------------------------------------------------------
-
- Include "Grammar";
-
- [ AnyWord; from_char=0; to_char=0; the_named_word=wn++; return burin; ];
-
- [ QuotedText i j f;
- i = WordAddress(wn++); i=i-buffer;
- if (buffer->i=='"')
- { for (j=i+1:j<=(buffer->1)+1:j++)
- if (buffer->j=='"') f=j;
- if (f==0) return -1;
- from_char = i+1; to_char=f-1;
- if (from_char>to_char) return -1;
- while (buffer+f > WordAddress(wn)) wn++; wn++;
- return burin;
- }
- return -1;
- ];
-
- Verb "write" "scribe"
- * AnyWord "on" held -> WriteOn
- * QuotedText "on" held -> WriteOn;
- Verb "copy" * scope=CopyableSpell "to" noun -> CopyTo;
- Verb "who" "what" "how"
- * "do" scope=Topic -> Query
- * "is" scope=Topic -> Query
- * "was" scope=Topic -> Query;
- Verb "spells" "memory"
- * -> Spells;
- Verb "learn" "memorise" "memorize"
- * scope=ReadableSpell -> Learn;
- Extend "examine" first
- * scope=ReadableSpell -> Examine;
- Verb "c,cast"
- * -> CastOne
- * noun -> CastOne;
- Verb "cast"
- * is_spell -> Cast
- * is_spell "at" noun -> Cast
- * is_spell "on" noun -> Cast;
- Verb "diagnose" "health"
- * -> Diagnose;
-
- ! ----------------------------------------------------------------------------
- ! And one for the game itself.
- ! ----------------------------------------------------------------------------
-
- Verb "ride" "mount" "straddle"
- * creature -> Ride
- * noun -> Enter;
- Verb "flip" "toss" * is_coin -> TossCoin;
- ! ----------------------------------------------------------------------------
-